package secondweek.four;

import org.junit.Assert;
import org.junit.Test;
import org.nutz.lang.*;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.sql.Time;
import java.util.*;

/**
 * Created by zhourui on 2016/8/11.
 * 随机生成 Salary {name, baseSalary, bonus  }的记录，如“wxxx,10,1”，每行一条记录，总共1000万记录，写入文本文件（UFT-8编码），
 然后读取文件，name的前两个字符相同的，其年薪累加，比如wx，100万，3个人，最后做排序和分组，输出年薪总额最高的10组：
 wx, 200万，10人
 lt, 180万，8人
 ....
 */
public class SaveAndSortSalary {

    @Test
    public void test(){
        File file = new File("D:\\aaa.txt");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //生成数据，写入文件
        Date timeBegin = Times.now();

//        writeFile(file);
        writeFileUseFileWriter(file);
//        writeFileUseFileWriter(file);

        Date afterWriteFile = Times.now();
        System.out.println("write file:" + (afterWriteFile.getTime()-timeBegin.getTime()) + "ms");

        //读取文件，排序
        List<Salary> salaries = readFile(file);
//        List<Salary> salaries = readFileUseChannel(file);

        Date afterReadFile = Times.now();
        System.out.println("read file:" + (afterReadFile.getTime()-afterWriteFile.getTime()) + "ms");

        Collections.sort(salaries, new Comparator<Salary>() {
            public int compare(Salary o1, Salary o2) {
                if (o1.getName().charAt(0) > o2.getName().charAt(0)){
                    return 1;
                } else if (o1.getName().charAt(0) == o2.getName().charAt(0)){
                    if (o1.getName().charAt(1) > o2.getName().charAt(1)){
                        return 1;
                    }else if (o1.getName().charAt(1) == o2.getName().charAt(1)){
                        return 0;
                    }else{
                        return -1;
                    }
                }
                return -1;
            }
        });

        Date afterSort = Times.now();
        System.out.println("sort list:" + (afterSort.getTime()-afterReadFile.getTime()) + "ms");

        //比较位置
        List<SalaryTeam> indexList = new ArrayList<SalaryTeam>();
        int from = 0;
        for (int i = 0; i < salaries.size()-1; i++){
            if(!compareFirstTwoWords(salaries.get(i),salaries.get(i+1))){
                SalaryTeam salaryTeam = new SalaryTeam(from,i,calFromToTotal(from,i,salaries));
                indexList.add(salaryTeam);
                from = i+1;
            }
        }
        //添加最后一个
        SalaryTeam salaryTeam = new SalaryTeam(from,salaries.size()-1,calFromToTotal(from,salaries.size()-1,salaries));
        indexList.add(salaryTeam);

//        System.out.println(indexList.get(0).toString());
//        System.out.println(indexList.get(indexList.size()-1).toString());

        Collections.sort(indexList, new Comparator<SalaryTeam>() {
            public int compare(SalaryTeam o1, SalaryTeam o2) {
                return o1.getTotal() - o2.getTotal();
            }
        });

        if (indexList.size() > 10){
            for (int i = indexList.size()-1; i > indexList.size()-11; i--){
                System.out.println(salaries.get(indexList.get(i).getFrom()).getName().substring(0,2)+","+indexList.get(i).getTotal()+"万,"+(indexList.get(i).getTo()-indexList.get(i).getFrom()+1)+"人");
            }
        }

        Date getTenTop = Times.now();
        System.out.println("get top ten:" + (getTenTop.getTime()-afterSort.getTime()) + "ms");

        System.out.println("total:" + (getTenTop.getTime()-timeBegin.getTime()) + "ms");


        Files.deleteFile(file);
    }

    private void writeFile(File file){
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        try {
            fos = new FileOutputStream(file,false);
            osw = new OutputStreamWriter(fos, Encoding.CHARSET_UTF8);
            for (int i = 0; i < 10000000; i++){
                Salary salary = new Salary(generateSixChar(), (new Random().nextInt(10)+1),new Random().nextInt(50));
                osw.write(salary.toString()+"\n");
//                if (i % 10000 == 0){
//                    osw.flush();
//                }
            }
        } catch (IOException var7) {
            throw Lang.wrapThrow(var7);
        } finally {
            if (osw != null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void writeFileUseFileWriter(File file){
        FileWriter fw = null;
        try {
            fw = new FileWriter(file,true);
            for (int i = 0; i < 10000000; i++){
                Salary salary = new Salary(generateSixChar(), (new Random().nextInt(10)+1),new Random().nextInt(50));
                fw.write(salary.toString()+"\n");
            }
        } catch (IOException var7) {
            throw Lang.wrapThrow(var7);
        } finally {
            if (fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private List<Salary> readFile(File file){
        List<Salary> salaries = new ArrayList<Salary>();
        String eachLine;
        InputStream is = null;
        BufferedInputStream bfs = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            is = new FileInputStream(file);
            bfs =new BufferedInputStream(is);
            isr = new InputStreamReader(bfs, Encoding.CHARSET_UTF8);
            br = new BufferedReader(isr);
            while(br.ready()) {
                eachLine = br.readLine();
                if (Strings.isNotBlank(eachLine)){
                    String[] salaryStrings = eachLine.split(",");
                    Salary salary = new Salary(salaryStrings[0], Integer.parseInt(salaryStrings[1]),Integer.parseInt(salaryStrings[2]));
                    salaries.add(salary);
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (isr != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bfs != null){
                try {
                    bfs.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return salaries;
    }

    private int calFromToTotal(int from,int to,List<Salary> salaries){
        int total = 0;
        for (int i = from; i <= to; i++){
            total += salaries.get(i).getBaseSalary() * 12 + salaries.get(i).getBonus();
        }
        return total;
    }

    private boolean compareFirstTwoWords(Salary salary0, Salary salary1){
        if (salary0.getName().charAt(0) == salary1.getName().charAt(0)
                && salary0.getName().charAt(1) == salary1.getName().charAt(1)){
            return true;
        }
        return false;
    }

    private static String generateSixChar(){
        String a = "abcdefghijklmnopqrstuvwxyz";
        char[] rands = new char[4];
        for (int i = 0; i < rands.length; i++)
        {
            int rand = (int) (Math.random() * a.length());
            rands[i] = a.charAt(rand);
        }
        return new String(rands);
    }


    @Test
    public void testChar(){
        Assert.assertEquals(true,"a".charAt(0) < "b".charAt(0));
        Assert.assertEquals(true,"ab".charAt(1) < "bc".charAt(1));
        Assert.assertEquals(true,"a".charAt(0) == "a".charAt(0));
    }
}
